package hxm.monads;

/**
 * A monad for working with iterators.
 * 
 * @author Simon Krajewski
 */

class IteratorMonad 
{
	inline static public function bind<A, B>(a:Iterator<A>, f:A -> Iterator<B>):Iterator<B>
	{
		var ret = new List<B>();
		for  (b in a)
			for (c in f(b))
				ret.add(c);
		return ret.iterator();
	}
	
	inline static public function map<A, B>(a:Iterator<A>, f:A->B):Iterator<B>
	{
		var ret = new List<B>();
		for (i in a)
			ret.add(f(i));
		return ret.iterator();
	}

	inline static public function yield<A>(a:A):Iterator<A>
	{
		var ret = new List<A>();
		ret.add(a);
		return ret.iterator();
	}
	
	static public var zero = new ZeroIterator();

	static public function plus<A>(a:Iterator<A>, b:Iterator<A>):Iterator<A>
	{
		var ret = new List<A>();
		for (i in a) ret.push(i);
		for (i in b) ret.push(i);
		return ret.iterator();
	}
}

class ZeroIterator
{
	public function new() { }
	public function hasNext() return false
	public function next():Int
	{
		throw "Not implemented";
		return 0;
	}
}